﻿using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BaiTu.Common;

namespace BaiTu.RedisExecutors
{
    /// <summary>
    /// Redis 执行的操作
    /// </summary>
    public class RedisExecutor
    {
        private static RedisClient RedisClient
        {
            get
            {
                return BaiTu.CachingClientManager.RedisClientManager.RedisFactory.GetRedisClient();
            }
        }

        private static RedisClient RedisClientReadOnly
        {
            get
            {
                return BaiTu.CachingClientManager.RedisClientManager.RedisFactory.GetReadOnlyClient();
            }
        }

        private static string KeyNotNull = "redis key 不能为null";
        private static string ValueNotNull = "redis value 不能为null";
        #region 字符串操作

        /// <summary>
        /// 获取指定key值的长度
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public long STRLEN(string key)
        {
            key.MustNotNull(KeyNotNull);
            using (RedisClient client = RedisClientReadOnly)
            {
                return client.StrLen(key);
            }
        }

        public long SETNX(string key, string value)
        {
            key.MustNotNull(KeyNotNull);
            value.MustNotNull(ValueNotNull);
            using (RedisClient client = RedisClient)
            {
                return client.SetNX(key, Common.Helpers.TypeConverterHelper.StringToByte(value));
            }
        }

        public void SETEX(string key, int expireSeconds, string value)
        {
            key.MustNotNull(KeyNotNull);
            value.MustNotNull(ValueNotNull);
            using (RedisClient client = RedisClient)
            {
                client.SetEx(key, expireSeconds, Common.Helpers.TypeConverterHelper.StringToByte(value));
            }

        }
        /// <summary>
        /// 如果过期时间不设置  则默认为永久有效
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expireSeconds"></param>
        public void SET(string key, string value, int expireSeconds = -1)
        {
            key.MustNotNull(KeyNotNull);
            value.MustNotNull(ValueNotNull);

            using (RedisClient client = RedisClient)
            {
                if (expireSeconds == -1)
                {
                    client.Set(key, Common.Helpers.TypeConverterHelper.StringToByte(value));
                }
                else
                {
                    client.Set(key, Common.Helpers.TypeConverterHelper.StringToByte(value), expireSeconds);
                }
            }

        }

        #endregion


        #region list 集合操作
        /// <summary>
        /// 获取集合中的key 的值的长度
        /// </summary>
        /// <param name="listID"></param>
        /// <returns></returns>
        public static long LLEN(string listID)
        {
            using (RedisClient client = RedisClientReadOnly)
            {

                return client.LLen(listID);
            }
        }

        /// <summary>
        /// 移除并且返回 key 对应的 list 的第一个元素。
        /// </summary>
        /// <param name="listID"></param>
        /// <returns></returns>
        public static string LPOP(string listID)
        {
            using (RedisClient client = RedisClient)
            {
                return Common.Helpers.TypeConverterHelper.ByteToString(client.LPop(listID), true);
            }
        }
        /// <summary>
        /// 在 push 操作后的 list 长度。
        /// </summary>
        /// <param name="listID"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long LPUSH(string listID, string value)
        {
            value.MustNotNull(ValueNotNull);
            using (RedisClient client = RedisClient)
            {
                return client.LPush(listID, Common.Helpers.TypeConverterHelper.StringToByte(value));
            }

        }
        public static long LPUSH(string listID, byte[] value)
        {
            value.MustNotNull(ValueNotNull);
            using (RedisClient client = RedisClient)
            {
                return client.LPush(listID, value);
            }

        }

        public static byte[] BRPopValue(string listID, int timeOutSecons = 0)
        {
            using (RedisClient client = RedisClientReadOnly)
            {
                return client.BRPopValue(listID, timeOutSecons);
            }
        }
        /// <summary>
        /// 在 push 操作后的 list 长度。
        /// </summary>
        /// <param name="listID"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long LPUSHX(string listID, string value)
        {
            value.MustNotNull(ValueNotNull);
            using (RedisClient client = RedisClient)
            {
                return client.LPushX(listID, Common.Helpers.TypeConverterHelper.StringToByte(value));
            }

        }

        public static string RPOP(string listID)
        {
            using (RedisClient client = RedisClientReadOnly)
            {
                return Common.Helpers.TypeConverterHelper.ByteToString(client.RPop(listID), true);
            }

        }

        public static long RPUSH(string listID, string value)
        {
            value.MustNotNull(ValueNotNull);
            using (RedisClient client = RedisClientReadOnly)
            {
                return client.RPush(listID, Common.Helpers.TypeConverterHelper.StringToByte(value));
            }

        }

        public static byte[][] BLPOP(string listID, int timeOutSeconds = 1)
        {
            using (RedisClient client = RedisClientReadOnly)
            {
                return client.BLPop(listID, timeOutSeconds);
            }

        }

        public static byte[][] BRPOP(string listID, int timeOutSeconds = 1)
        {
            using (RedisClient client = RedisClientReadOnly)
            {
                return client.BRPop(listID, timeOutSeconds);
            }

        }
        #endregion

        #region Common
        public static bool ContainsKey(string key)
        {
            using (RedisClient client = RedisClientReadOnly)
            {
                return client.ContainsKey(key);
            }
        }

        public static bool Remove(string key)
        {
            using (RedisClient client = RedisClient)
            {
                return client.Remove(key);
            }
        }

        public static string GetValue(string key)
        {
            using (RedisClient client = RedisClientReadOnly)
            {
                return client.GetValue(key);
            }
        }

        public static bool Add<T>(string key, T value, DateTime dtExpireTime)
        {

            using (RedisClient client = RedisClient)
            {
                return client.Add(key, value, dtExpireTime);
            }
        }
        #endregion
    }
}
